package com.gupao.rpc.protocol.spring.reference;

import com.gupao.rpc.protocol.client.NettyClient;
import com.gupao.rpc.protocol.constants.ReqType;
import com.gupao.rpc.protocol.constants.RpcConstant;
import com.gupao.rpc.protocol.constants.SerialType;
import com.gupao.rpc.protocol.protocol.*;
import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

@Slf4j
public class RpcInovkerProxy implements InvocationHandler {

    private String host;
    private int port;

    public RpcInovkerProxy(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long requestId = RequestHolder.REQUEST_ID.incrementAndGet();
        log.info("------->>>> begin invoke target server {} ont port {} requestId: {}", host, port, requestId);
        RpcProtocol<RpcRequest> reqProtocol = new RpcProtocol<>();
        Header header = new Header(RpcConstant.MAGIC, SerialType.JSON.value(),
                ReqType.REQUEST.value(), requestId, 0);
        reqProtocol.setHeader(header);
        RpcRequest request = new RpcRequest();
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameterTypes(method.getParameterTypes());
        request.setParameters(args);
        reqProtocol.setBody(request);

        NettyClient nettyClient = new NettyClient(host, port);
        RpcFuture<RpcResponse> future = new RpcFuture<>(new DefaultPromise<>(new DefaultEventLoop()));
        RequestHolder.REQUEST_MAP.put(requestId, future);
        nettyClient.sendRequest(reqProtocol);
        return future.getPromise().get().getData();
    }

}
